package com.ibiaoke.marketing.service;

import com.google.common.collect.Lists;
import com.ibiaoke.common.consts.CommonConsts;
import com.ibiaoke.common.exception.ServiceException;
import com.ibiaoke.common.utils.AssertUtils;
import com.ibiaoke.common.consts.BusinessDef;
import com.ibiaoke.common.utils.StringUtils;
import com.ibiaoke.customer.dao.ThirdPartLoginDao;
import com.ibiaoke.customer.entity.ThirdPartLogin;
import com.ibiaoke.goods.dao.GoodsDao;
import com.ibiaoke.goods.entity.Goods;
import com.ibiaoke.marketing.consts.CouponGroupDef;
import com.ibiaoke.marketing.consts.CouponReceiveConsts;
import com.ibiaoke.marketing.dao.CouponDao;
import com.ibiaoke.marketing.dao.CouponReceiveDao;
import com.ibiaoke.marketing.entity.Coupon;
import com.ibiaoke.marketing.entity.CouponReceive;
import com.ibiaoke.marketing.entity.vo.CouponReceiveVO;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by huhaichao on 2017/6/14.
 */

@Service
public class CouponReceiveServiceImpl implements CouponReceiveService {

    //可用的
    private static final int AVAILABLE = 1;

    //已经用过但是还没过期
    private static final int USED = 2;

    //已经过期
    private static final int EXPIRED = 3;

    @Autowired
    private CouponReceiveDao couponReceiveDao;
    @Autowired
    private CouponDao couponDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private CouponService couponService;
    @Autowired
    private ThirdPartLoginDao thirdPartLoginDao;

    /**
     * 根据type类型获取对应的优惠券列表
     *
     * @param customerId
     * @param type
     * @return
     */
    @Override
    public List<CouponReceive> listCouponReceiveByType(Integer customerId, Integer type) {
        AssertUtils.notNull(type, "type不能为空");
        List<CouponReceive> couponReceives = Collections.emptyList();
        ;
        if (type == AVAILABLE) {
            couponReceives = couponReceiveDao.listUnusedCouponReceive(customerId);
        }
        if (type == USED) {
            couponReceives = couponReceiveDao.listUsedCouponReceive(customerId);
        }
        if (type == EXPIRED) {
            couponReceives = couponReceiveDao.listExpiredCouponReceive(customerId);
        }
        return filterGoodsName(couponReceives);
    }

    public List<CouponReceive> filterGoodsName(List<CouponReceive> couponReceives) {
        if (CollectionUtils.isEmpty(couponReceives)) {
            return couponReceives;
        }

        List<Integer> goodsIds = couponReceives.stream()
                .filter(couponReceive -> Objects.equals(couponReceive.getUseType(),CouponReceiveConsts.USE_TYPE_GOODS))
                .map(CouponReceive::getCanUseId)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(goodsIds)) {
            return couponReceives;
        }
        List<Goods> goodsList = goodsDao.listByIds(goodsIds, null);

        couponReceives.forEach(couponReceive -> goodsList.forEach(goods -> {
            if (Objects.equals(couponReceive.getUseType(), CouponReceiveConsts.USE_TYPE_GOODS)
                    && Objects.equals(goods.getGoodsId(), couponReceive.getCanUseId())) {
                couponReceive.setGoodsName(goods.getName());
            }
        }));
        return couponReceives;
    }


    /**
     * 查询订单可用的优惠券列表
     *
     * @return
     * @Param userId
     * @Param fullPrice
     */
    @Override
    public List<CouponReceive> listCouponReceive(Integer customerId, BigDecimal fullPrice, String goodsIds) {
        AssertUtils.requireTrue(fullPrice.doubleValue() > 0, "没有可用优惠券");
        List<CouponReceive> couponReceives = couponReceiveDao.listCouponReceive(customerId, fullPrice);

        if (StringUtils.isNotEmpty(goodsIds)) {
            List<Integer> goodsIdList = Arrays.asList(goodsIds.split(CommonConsts.SPLIT_CHAR)).stream()
                    .map(Integer::parseInt).collect(Collectors.toList());

            List<CouponReceive> canNotUseCouponReceive = couponReceives.stream()
                    .filter(couponReceive -> Objects.equals(couponReceive.getUseType(), CouponReceiveConsts.USE_TYPE_GOODS)
                            && !goodsIdList.contains(couponReceive.getCanUseId()))
                    .collect(Collectors.toList());

            couponReceives.removeAll(canNotUseCouponReceive);

        }
        return filterGoodsName(couponReceives);
    }

    /**
     * 领取优惠券
     *
     * @param couponId
     * @return
     */
    @Transactional
    @Override
    public int receiveCoupon(int userId, int couponId) {
        long count = couponReceiveDao.countCoupon(userId, couponId, BusinessDef.DEFAULT, 0);
        AssertUtils.requireTrue(count <= 0, "你已领取过该优惠券");
        return receiveCouponNonCountLimit(userId, couponId, BusinessDef.DEFAULT, 0);
    }

    @Override
    public int receiveCouponNonCountLimit(int userId, String couponGroup) {
        List<Coupon> coupons = couponDao.listCoupon(couponGroup);
        if(CollectionUtils.isNotEmpty(coupons)) {
            Coupon coupon = coupons.get(0);
            return receiveCouponNonCountLimit(userId, coupon.getCouponId(), BusinessDef.DEFAULT, 0);
        }
        return 0;
    }

    /**
     * 领取优惠券，每个业务每张优惠券只能领取1次
     *
     * @param userId       领取人id
     * @param couponId     优惠券id
     * @param businessType 业务类型
     * @param businessId   业务id
     * @return
     */
    @Transactional
    @Override
    public int receiveCouponWithBusiness(int userId, int couponId, String businessType, int businessId) {
        long count = couponReceiveDao.countCoupon(userId, couponId, businessType, businessId);
        AssertUtils.requireTrue(count <= 0, "你已领取过该优惠券");
        return receiveCouponNonCountLimit(userId, couponId, businessType, businessId);
    }

    private int receiveCouponNonCountLimit(int userId, int couponId, String businessType, int businessId) {
        Coupon coupon = couponDao.selectByPrimaryKey(couponId);
        AssertUtils.requireTrue(coupon != null && coupon.getDelStatus() == CommonConsts.NO, "优惠券不存在");
        if (coupon.getScopeType() == 1) {
            if (coupon.getReceiveBeginTime().after(new Date())) {
                throw new ServiceException("未到领取时间");
            }
            if (coupon.getReceiveEndTime().before(new Date())) {
                throw new ServiceException("领取时间已过");
            }
        }
        if (coupon.getTotalCount() - coupon.getReceivedCount() <= 0) {
            throw new ServiceException("优惠券已经被领完");
        }

        CouponReceive couponReceive = new CouponReceive();
        couponReceive.setUserId(userId);
        couponReceive.setCouponId(couponId);
        couponReceive.setScopeType(coupon.getScopeType());
        couponReceive.setCouponName(coupon.getCouponName());
        couponReceive.setDurationDay(coupon.getDurationDay());
        couponReceive.setBusinessType(businessType);
        couponReceive.setBusinessId(businessId);
        couponReceive.setUseType(coupon.getUseType());
        couponReceive.setCanUseId(coupon.getCanUseId());

        couponReceive.setFullPrice(coupon.getFullPrice());
        if (coupon.getScopeType() == 1) {
            couponReceive.setUseBeginTime(coupon.getUseBeginTime());
            couponReceive.setUseEndTime(coupon.getUseEndTime());
        }
        if (coupon.getScopeType() == 2) {
            couponReceive.setUseBeginTime(new Date());
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, coupon.getDurationDay());
            couponReceive.setUseEndTime(calendar.getTime());
        }
        if (coupon.getPriceType() == 0) {
            couponReceive.setCouponPrice(coupon.getCouponPrice());
        }
        if (coupon.getPriceType() == 1) {
            double random = Math.random();
            double price = (random * coupon.getCouponPrice().doubleValue());
            if (price < 2) {
                price += 2;
            }
            couponReceive.setCouponPrice(new BigDecimal(String.valueOf(price)).setScale(2, BigDecimal.ROUND_HALF_UP));
        }

        couponReceive.setUseStatus((byte) 0);
        couponReceive.setReceiveTime(new Date());
        return couponReceiveDao.insert(couponReceive);
    }


    @Override
    public void receiveRegCoupon(Integer customerId) {
        List<Coupon> coupons = couponDao.listCoupon(CouponGroupDef.NEW_USER);
        if (CollectionUtils.isNotEmpty(coupons)) {
            for (Coupon cur : coupons) {
                int count = this.receiveCoupon(customerId, cur.getCouponId());
                if (count > 0) {
                    couponService.updateCouponNum(cur.getCouponId());
                }
            }

        }
    }

    @Override
    public CouponReceive getCouponReceive(Integer couponReceiveId) {
        return couponReceiveDao.selectByPrimaryKey(couponReceiveId);
    }

    @Override
    public CouponReceive useCouponReceive(Integer couponReceiveId, BigDecimal price) {
        AssertUtils.notNull(couponReceiveId, "请选择优惠券");
        CouponReceive couponReceive = couponReceiveDao.selectByPrimaryKey(couponReceiveId);
        AssertUtils.requireTrue(couponReceive.getUseStatus() == CommonConsts.NO, "优惠券已使用");
        AssertUtils.requireTrue(price.compareTo(couponReceive.getFullPrice()) >= 0, "优惠券不可用");
        AssertUtils.requireTrue(couponReceive.getUseBeginTime().before(new Date()), "优惠券已经过期");
        AssertUtils.requireTrue(couponReceive.getUseEndTime().after(new Date()), "优惠券已经过期");
        couponReceiveDao.useCouponReceive(couponReceiveId);
        couponReceive.setUseStatus((byte) CommonConsts.YES);
        return couponReceive;
    }

    @Override
    public int releaseCoupon(Integer couponReceiveId) {
        return couponReceiveDao.releaseCoupon(couponReceiveId);
    }

    @Override
    public List<CouponReceiveVO> convert(List<CouponReceive> couponReceives) {
        List<CouponReceiveVO> couponReceiveVOs = Lists.newArrayList();
        List<Integer> userIds = couponReceives.parallelStream().map(CouponReceive::getUserId).collect(Collectors.toList());
        List<ThirdPartLogin> ThirdPartLogins = thirdPartLoginDao.listThirdPartLogin(userIds);
        for (CouponReceive couponReceive : couponReceives) {
            for (ThirdPartLogin thirdPartLogin : ThirdPartLogins) {
                if (couponReceive.getUserId().equals(thirdPartLogin.getUserId())) {
                    CouponReceiveVO receiveVO = new CouponReceiveVO();
                    receiveVO.setUserId(thirdPartLogin.getUserId());
                    receiveVO.setCouponPrice(couponReceive.getCouponPrice());
                    receiveVO.setReceiveTime(couponReceive.getReceiveTime());
                    receiveVO.setHeadImageUrl(thirdPartLogin.getHeadImageUrl());
                    receiveVO.setNickName(thirdPartLogin.getNickName());
                    couponReceiveVOs.add(receiveVO);
                    continue;
                }
            }
        }
        return couponReceiveVOs;
    }

    /**
     * 获取个人可用优惠券的数量
     *
     * @param customerId
     * @return
     */
    @Override
    public Long countUnusedCouponReceive(Integer customerId) {
        return couponReceiveDao.countUnusedCouponReceive(customerId);
    }
}
